package com.cssw.fyzb.tps.api.auth;

import com.cssw.fyzb.tps.config.auth.AccessTokenConfig;
import com.cssw.fyzb.tps.config.auth.AuthResultSign;
import com.cssw.fyzb.tps.exception.BizException;
import com.cssw.fyzb.tps.service.auth.tecent.AccessToken;
import com.cssw.fyzb.tps.service.auth.tecent.AuthResult;
import com.cssw.fyzb.tps.service.auth.tecent.SignTicket;
import com.cssw.fyzb.tps.util.SignUtil;
import com.ydn.appserver.Action;
import com.ydn.appserver.Request;
import com.ydn.appserver.Response;
import com.ydn.appserver.annotations.Function;
import com.ydn.appserver.annotations.Parameter;
import com.ydn.appserver.annotations.Type;
import com.ydn.simplelock.SimpleLock;
import com.ydn.simplelock.SimpleLockFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 人脸核身结果查询
 *
 * @Author zhouxu
 * @create 2020-09-15 16:45
 */
@Function(description = "人脸核身结果查询", parameters = {
        @Parameter(name = "userId", type = Type.String, description = "用户ID", required = true),
        @Parameter(name = "orderNo", type = Type.String, description = "订单号", required = true),
        @Parameter(name = "nonce", type = Type.String, description = "随机数", required = true),

})
@Component
public class TecentFaceAuthQuery implements Action {

    private static final Logger logger = LoggerFactory.getLogger(TecentFaceAuthQuery.class);

    @Autowired
    private AuthResult authResult;

    @Autowired
    private SignTicket signTicket;

    @Autowired
    private AccessToken accessToken;

    @Autowired
    private SimpleLockFactory simpleLockFactory;

    @Override
    public Response execute(Request request) throws Exception {
        String orderNo = request.getString("orderNo");
        String userId = request.getString("userId");
        String nonce = request.getString("nonce");

        SimpleLock simpleLock = simpleLockFactory.getLock(AccessToken.KEY_PREX + accessToken.getAppId());
        AccessTokenConfig accessHttpResult = null;

        try {
            simpleLock.acquire();
            // 获取 Access Token
            accessHttpResult = accessToken.getAccessToken();
        } catch (BizException be) {
            logger.error(be.getErrMsg(), be.getErrCode());
            return Response.fail(be.getErrMsg(), be.getErrCode());
        } catch (Exception e) {
            logger.error("获取 access token 失败:", e);
            return Response.fail(e);
        } finally {
            try {
                simpleLock.release();
            } catch (Exception e) {
                logger.error("", e);
                Response.fail("释放锁失败");
            }
        }

        logger.debug("AccessToken 返回：" + accessHttpResult.toString());
        String accessToken = accessHttpResult.getAccessToken();
        SignTicket.HttpResult signHttpResult = null;
        try {
            // 获取 sign Ticket
            signHttpResult = signTicket.getSignTicket(userId, accessToken);
        } catch (BizException be) {
            logger.error(be.getErrMsg(), be.getErrCode());
            return Response.fail(be.getErrMsg(), be.getErrCode());
        } catch (Exception e) {
            logger.error("", e);
            return Response.fail(e);
        }


        List<SignTicket.Ticket> tickets = signHttpResult.getTickets();
        SignTicket.Ticket ticket = tickets.get(0);
        String ticketValue = ticket.getValue();

        // 数字签名
        String sign = getSign(
                new AuthResultSign(authResult.getAppId(), orderNo, authResult.getVersion(), ticketValue, nonce)
        );
        logger.debug("sign:" + sign);

        AuthResult.HttpResult result = null;
        try {

            // 查询身份认证结果
            result = authResult.getResultInfo(orderNo, sign, nonce);
            return Response.success().put("data", result);
        } catch (BizException be) {
            logger.error(be.getErrMsg(), be.getErrCode());
            return Response.fail(be.getErrMsg(), be.getErrCode());
        } catch (Exception e) {
            logger.error("", e);
            return Response.fail(e);
        }

    }

    private String getSign(AuthResultSign sign) {
        List<String> values = new ArrayList<>();
        values.add(sign.getAppId());
        values.add(sign.getOrderNo());
        values.add(sign.getVersion());
        values.add(sign.getNonce());
        logger.debug("数字签名参数:" + sign.toString());
        return SignUtil.sign(values, sign.getTicketValue());
    }


}
